package sk.ygor.raynor.client.test;

import com.google.gwt.json.client.*;

public class JSONBuilder {

    public static JSONNull nul() {
        return JSONNull.getInstance();
    }

    public static JSONNumber number(Number value) {
        return new JSONNumber(value.doubleValue());
    }

    public static JSONString string(String value) {
        return new JSONString(value);
    }

    public static JSONBoolean bool(Boolean value) {
        return JSONBoolean.getInstance(value);
    }

    public static JSONArray array(JSONValue... members) {
        JSONArray array = new JSONArray();
        int i = 0;
        for (JSONValue member : members) {
            array.set(i++, member);
        }
        return array;
    }

    public static class JSONObjectProperty {

        private final String name;

        private final JSONValue value;

        public JSONObjectProperty(String name, JSONValue value) {
            this.name = name;
            this.value = value;
        }

    }

    public static JSONObjectProperty propNull(String name) {
        return new JSONObjectProperty(name, nul());
    }

    public static JSONObjectProperty prop(String name, JSONObject value) {
        return new JSONObjectProperty(name, value);
    }

    public static JSONObjectProperty prop(String name, JSONArray value) {
        return new JSONObjectProperty(name, value);
    }

    public static JSONObjectProperty prop(String name, String value) {
        return new JSONObjectProperty(name, string(value));
    }

    public static JSONObjectProperty prop(String name, Number value) {
        return new JSONObjectProperty(name, number(value));
    }

    public static JSONObjectProperty prop(String name, Boolean value) {
        return new JSONObjectProperty(name, bool(value));
    }

    public static class ClassNamer {
        private final Class clazz;
        private final ClassNamer[] parameters;

        public ClassNamer(Class clazz, ClassNamer... parameters) {
            this.clazz = clazz;
            this.parameters = parameters;
        }

        public String className() {
            final StringBuffer result = new StringBuffer();
            result.append(clazz.getName().replaceAll("\\$", "\\."));
            if (parameters.length > 0) {
                result.append("[");
                for (int i = 0; i < parameters.length; i++) {
                    result.append(parameters[i].className());
                    if (i < parameters.length - 1) {
                        result.append(",");
                    }
                }
                result.append("]");
            }
            return result.toString();
        }
    }

    public static JSONObject object(Class clazz, JSONObjectProperty... properties) {
        return object(new ClassNamer(clazz), properties);
    }
    public static JSONObject object(ClassNamer classNamer, JSONObjectProperty... properties) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("_class", string(classNamer.className()));
        for (JSONObjectProperty property : properties) {
            jsonObject.put(property.name, property.value);
        }
        return jsonObject;
    }
}
